"""
问题1主求解器 - 定日镜场布局优化设计 (修复版本)
严格按照流程: 阶段1→阶段2→阶段3→结果输出
"""

import time
import numpy as np
import math
import matplotlib.pyplot as plt
from data_preprocess import DataPreprocessor
from efficiency_calc import EfficiencyCalculator
from genetic_algorithm import GeneticAlgorithm

class Problem1Solver:
    def __init__(self):
        """初始化问题1求解器"""
        self.preprocessor = DataPreprocessor()
        self.efficiency_calc = EfficiencyCalculator()
        
        # 存储中间结果
        self.solar_positions = None
        self.candidate_positions = None
        self.dni_avg = None
        self.geometry_data = None
        
        print("🎯 问题1求解器初始化完成 (修复版本)")
        print("   目标: 给定条件下的定日镜场性能计算与优化")
    
    def solve_problem1(self):
        """求解问题1 - 完整流程"""
        print("\n" + "="*80)
        print("🚀 开始求解问题1: 定日镜场布局优化设计")
        print("="*80)
        
        start_time = time.time()
        
        # 阶段1: 初始化与预处理 (代码可复用模块)
        print("\n📋 阶段1: 初始化与预处理")
        print("-" * 50)
        
        self._stage1_preprocessing()
        
        # 阶段2: 遗传算法优化 (核心代码模块)
        print("\n🧬 阶段2: 遗传算法优化")
        print("-" * 50)
        
        best_solution, best_fitness = self._stage2_genetic_optimization()
        
        # 阶段3: 光学效率计算与验证 (详细代码模块)
        print("\n🔬 阶段3: 光学效率计算与验证")
        print("-" * 50)
        
        detailed_results = self._stage3_efficiency_verification(best_solution)
        
        # 结果输出与可视化
        print("\n📊 结果分析与可视化")
        print("-" * 50)
        
        self._output_results(best_solution, detailed_results)
        
        end_time = time.time()
        
        print(f"\n✅ 问题1求解完成! 总耗时: {end_time - start_time:.2f} 秒")
        print("="*80)
        
        return best_solution, detailed_results
    
    def _stage1_preprocessing(self):
        """阶段1: 数据预处理"""
        print("1. 数据准备:")
        
        # 加载场地边界数据
        x_coords, y_coords = self.preprocessor.load_boundary_data()
        
        # 加载气象数据 (DNI小时值, 太阳高度角/方位角)
        print("   • 采集气象数据: DNI小时值, 太阳轨迹预处理结果")
        
        # 生成全年时间点 (简化: 每天代表性时间点)
        time_points = self.preprocessor.generate_time_points()
        
        # 预计算太阳轨迹 (修复：每天中午12点代表性时间点)
        representative_times = [time_points[i] for i in range(12, len(time_points), 24)]  # 每天中午12点
        self.solar_positions = self.preprocessor.calculate_solar_position(representative_times)
        
        print("2. 可行域生成:")
        
        # 在圆形场地内，用高密度极坐标网格生成满足安全间距的候选位置集合 (标准化版本)
        self.candidate_positions = self.preprocessor.generate_candidate_positions(grid_size=2.0)  # 2m网格间距
        
        # 输出候选位置列表 candidate_positions (含 (x,y) 坐标)
        print(f"   • 候选位置集合: {len(self.candidate_positions)} 个")
        
        print("3. 预计算模块:")
        
        # 计算年平均DNI
        self.dni_avg, dni_values = self.preprocessor.calculate_dni_average(self.solar_positions)
        
        # 生成定日镜-吸收塔距离相离、定日镜间距离矩阵 (减少重复计算)
        self.geometry_data = self.preprocessor.precompute_geometry(self.candidate_positions)
        
        print("   ✅ 阶段1完成: 数据预处理")
    
    def _stage2_genetic_optimization(self):
        """阶段2: 遗传算法优化 - 修复版本"""
        print("🧬 初始化遗传算法...")
        
        # 创建遗传算法实例
        ga = GeneticAlgorithm(
            candidate_positions=self.candidate_positions,
            solar_positions=self.solar_positions,
            dni_avg=self.dni_avg
        )
        
        print("🚀 开始遗传算法优化...")
        
        # 修复: 使用新的optimize方法
        best_solution, best_fitness = ga.optimize()
        
        print(f"✅ 遗传算法优化完成")
        print(f"   最优适应度: {best_fitness:.6f}")
        
        # 解码最优解
        mirror_positions, tower_position = ga.decode_individual(best_solution)
        
        print(f"   定日镜数量: {len(mirror_positions)}")
        print(f"   吸收塔位置: ({tower_position[0]:.2f}, {tower_position[1]:.2f})")
        
        return (mirror_positions, tower_position), best_fitness

    def _stage3_efficiency_verification(self, solution):
        """阶段3: 光学效率计算与验证 - 修复版本"""
        mirror_positions, tower_position = solution
        
        print("🔬 开始详细光学效率计算...")
        
        # 修复: 使用新的综合结果计算方法
        detailed_results = self.efficiency_calc.calculate_comprehensive_results(
            mirror_positions, tower_position, self.solar_positions
        )
        
        return detailed_results
    
    def _decode_solution(self, solution):
        """解码遗传算法解"""
        N = solution[0]
        mirror_indices = solution[1:N+1]
        tower_x, tower_y = solution[N+1], solution[N+2]
        
        mirror_positions = [self.candidate_positions[idx] for idx in mirror_indices]
        tower_position = (tower_x, tower_y)
        
        return mirror_positions, tower_position
    
    def _calculate_total_power(self, efficiencies):
        """计算总输出功率"""
        mirror_area = 36  # 6m × 6m
        total_power = sum(eta * mirror_area * self.dni_avg for eta in efficiencies)
        return total_power
    
    def _output_results(self, solution, detailed_results):
        """输出最终结果 - 修复版本"""
        mirror_positions, tower_position = solution
        
        print("\n" + "="*80)
        print("📊 问题1最终结果")
        print("="*80)
        
        # 基础信息
        print(f"🏗️  布局信息:")
        print(f"   定日镜数量: {len(mirror_positions)} 个")
        print(f"   定日镜规格: {self.preprocessor.mirror_width}m × {self.preprocessor.mirror_height}m")
        print(f"   安装高度: {self.preprocessor.install_height}m")
        print(f"   吸收塔位置: ({tower_position[0]:.2f}, {tower_position[1]:.2f}) m")
        print(f"   吸收塔高度: {self.preprocessor.tower_height}m")
        
        # 性能指标
        print(f"\n⚡ 性能指标:")
        print(f"   年平均光学效率: {detailed_results.get('avg_efficiency', 0):.4f} ({detailed_results.get('avg_efficiency', 0)*100:.2f}%)")
        print(f"   年平均输出功率: {detailed_results.get('total_power', 0):,.0f} W ({detailed_results.get('total_power', 0)/1e6:.2f} MW)")
        print(f"   单镜平均功率: {detailed_results.get('power_per_mirror', 0):,.0f} W")
        print(f"   场地利用率: {detailed_results.get('field_utilization', 0)*100:.1f}%")
        
        # 约束检查
        print(f"\n🔍 约束检查:")
        violations = detailed_results.get('safety_violations', 0)
        violation_ratio = detailed_results.get('violation_ratio', 0)
        if violations > 0:
            print(f"   ⚠️  安全距离违约: {violations}个 ({violation_ratio:.1%})")
            print(f"   建议: 需要调整布局以满足8m最小安全距离")
        else:
            print(f"   ✅ 所有约束满足")
        
        # 绘制布局图
        self._plot_layout(mirror_positions, tower_position)
        
        return {
            'mirror_positions': mirror_positions,
            'tower_position': tower_position,
            'detailed_results': detailed_results,
            'summary': {
                'mirror_count': len(mirror_positions),
                'avg_efficiency': detailed_results.get('avg_efficiency', 0),
                'total_power': detailed_results.get('total_power', 0),
                'safety_violations': violations
            }
        }
    
    def _verify_constraints(self, mirror_positions, tower_position):
        """验证约束条件"""
        print("   • 约束验证:")
        
        # 场地边界约束
        field_violations = 0
        for x, y in mirror_positions:
            if x**2 + y**2 > self.preprocessor.R_field**2:
                field_violations += 1
        
        # 禁区约束
        keepout_violations = 0
        for x, y in mirror_positions:
            if x**2 + y**2 < self.preprocessor.R_keepout**2:
                keepout_violations += 1
        
        # 安全距离约束
        distance_violations = 0
        for i, pos1 in enumerate(mirror_positions):
            for j, pos2 in enumerate(mirror_positions):
                if i >= j:
                    continue
                dist = math.sqrt((pos1[0]-pos2[0])**2 + (pos1[1]-pos2[1])**2)
                if dist < 11:  # max(w,h) + 5 = 6 + 5 = 11m
                    distance_violations += 1
        
        print(f"     - 场地边界违约: {field_violations} 个")
        print(f"     - 禁区违约: {keepout_violations} 个")
        print(f"     - 安全距离违约: {distance_violations} 个")
    
    def _plot_layout(self, mirror_positions, tower_position):
        """绘制场地布局图 - 修复版本"""
        try:
            plt.figure(figsize=(12, 10))
            
            # 绘制场地边界
            circle_field = plt.Circle((0, 0), self.preprocessor.R_field, 
                                    fill=False, color='black', linewidth=2, label='场地边界')
            plt.gca().add_patch(circle_field)
            
            # 绘制禁区
            circle_keepout = plt.Circle((0, 0), self.preprocessor.R_keepout, 
                                      fill=True, alpha=0.3, color='red', label='禁区')
            plt.gca().add_patch(circle_keepout)
            
            # 绘制定日镜
            mirror_x = [pos[0] for pos in mirror_positions]
            mirror_y = [pos[1] for pos in mirror_positions]
            plt.scatter(mirror_x, mirror_y, c='blue', s=20, alpha=0.7, label=f'定日镜 ({len(mirror_positions)}个)')
            
            # 绘制吸收塔
            plt.scatter(tower_position[0], tower_position[1], c='red', s=200, 
                       marker='^', label='吸收塔')
            
            plt.xlim(-400, 400)
            plt.ylim(-400, 400)
            plt.xlabel('X坐标 (m)')
            plt.ylabel('Y坐标 (m)')
            plt.title('问题1: 定日镜场布局优化结果 (修复版本)')
            plt.legend()
            plt.grid(True, alpha=0.3)
            plt.axis('equal')
            
            # 保存图片
            plt.savefig('problem1_layout_fixed.png', dpi=300, bbox_inches='tight')
            print("     - 布局图已保存: problem1_layout_fixed.png")
            
            plt.close()
            
        except Exception as e:
            print(f"     - 绘图失败: {e}")

# 主程序入口
if __name__ == "__main__":
    print("🎯 问题1: 定日镜场布局优化设计 (修复版本)")
    print("   给定条件: 6m×6m定日镜, 4m安装高度, 吸收塔在(0,0)")
    
    # 创建求解器
    solver = Problem1Solver()
    
    # 求解问题1
    best_solution, detailed_results = solver.solve_problem1()
    
    print("\n🎊 问题1求解完成!")
    print("   详细结果已输出，布局图已保存") 